package cards;
import java.util.ArrayList;
import java.util.Stack;
/** the solution is a sequence of cards placed on the board according to the card positions
    example without border
*/
public class Solution extends Stack<Candidate>
{
    // The board is an 2D array.
	// 0123
	// 0..-.
	// 1---.
	// 2.---
	// 3..-.
	private Candidate[][] board = new Candidate[4][4];
	
	// card positions on the board
	// the first card position on the board are
	// {0,2}, {1,0}. {1,1}
						//    0  1  2  3  4  5  6  7
	private int[] row = 	{ 2, 0, 1, 2, 1, 2, 3, 2 };
	private int[] column =	{ 0, 1, 1, 1, 2, 2, 2, 3 };

	//  indices of adjacent cards in the solution.
	//                 0    1     2       3      4       5      6   7   
	int [] [] check2 = {{3},{2},{1,3,4},{0,2,5},{2,5},{3,4,6,7},{5},{5}};
	
	int [] [] check = {{},{},{1},{0,2},{2},{3,4},{5},{5}};
	
	
	
	
	public Solution(){
	}

	
	 // Checks whether a candidate with card CardChar is in 
	 // an adjacent position of the board position (row, column)
	 // @param row, column, candidate
	 // @return Boolean indicating if cardChar is found.
	 // can be used in the methods fits and isCorrect
	private boolean bordersCard(int row, int column, char cardChar){
		
		Candidate adjacent = board[row][column];
		if(adjacent.getCardChar() == cardChar || cardChar == '?'){	
			return true;
		} else {
			return false;
		}
					
   }
	/**
	 * Checks whether candidate card of same kind.
	 * Checks whether by placing candidate the solution sofar still complies with the rules
	 * @param candidate
	 * @return boolean indicating whether this candidate can be put in the
	 * next free position.
	 */
	public boolean fits(Candidate candidate){ 
					
			int i=this.size();
			
			int[] temp = check[i];
							
			if(temp.length > 0){
									
				for(int j = 0; j < temp.length; j++){
						
					if(bordersCard(row[temp[j]], column[temp[j]], candidate.getCardChar()) && candidate.getAvailable() > 0){
							
						return false;							
					}								
				}
												
				if(!isCorrect()){					
					return false;
				}								
			}																								
			return true;
    }

	public void record(Candidate candidate)
	{
		int i=this.size(); // i= index in this stack of next for the next candidate
		board [row[i]] [column[i]] = candidate; //x=row, y=column
		this.push(candidate);
		//System.out.println("PUT " + candidate.getCardChar() +" ON X: " + row[i] + " Y: " + column[i]);
	}

	public boolean complete()
	{
		return this.size()==8;
	}

	public void show()
	{
		if(isCorrect()){
			System.out.println("#####################"); 
			System.out.println("Solution: ");
//			for(int i = 0; i < row.length; i++){
//				Candidate temp = this.get(i);
//				System.out.println(temp.getCardChar() + " ON X: " + row[i]  + " Y: " + column[i] );
//			}
			System.out.println("      " + this.get(0).getCardChar());
			System.out.println("" + this.get(1).getCardChar() + "  " + this.get(2).getCardChar() + "  " + this.get(3).getCardChar());
			System.out.println("   " + this.get(4).getCardChar() + "  " + this.get(5).getCardChar() + "  " + this.get(6).getCardChar());
			System.out.println("      " + this.get(7).getCardChar());
		}
		
	}

	public Candidate eraseRecording()
	{
		int i=this.size()-1;           // i= index of the candidate that is removed from this Stack;
		board[row[i]][column[i]]=null; // remove candidate from board
		//System.out.println("REMOVED CANDIDATE ON X: " + row[i] + " Y: " + column[i]);
		return this.pop();
    }
	
	// can be used in method isCorrect
    private char mustBeAdjacentTo(char card)
    {  
      if (card=='A') return 'K'; 
      if (card=='K') return 'Q'; 
      if (card=='Q') return 'J';
      return '?'; //error
    }
	
	/**
	 * Checks whether the rules below are fulfilled
	 * For the positions that can be checked for solution sofar.
	 * Rules:
	 * Elke aas (ace) grenst (horizontaal of verticaal) aan een heer (king).
	 * Elke heer grenst aan een vrouw (queen).
	 * Elke vrouw grenst aan een boer (jack).
	 * @return true if all checks are correct.
	 */
	// uses methods borderCard and mustBeAdjacent to
	private boolean isCorrect() {
		
		boolean correct = true;
		
		for(int i = 0; i < this.size(); i++){
			
			Candidate current = board[row[i]][column[i]];
			
			int[] temp = check2[i];
			
			if(temp.length > 0){
				
				boolean found = false;
				
				for(int j = 0; j < temp.length; j++){
					
					Candidate adjacent = board[row[temp[j]]][column[temp[j]]];
					
					if(adjacent == null){
						found = true;
					} else {
						if(bordersCard(row[temp[j]], column[temp[j]], mustBeAdjacentTo(current.getCardChar()))){
							
							found = true;			
						}
					}									 
				}
				if(!found){
					return false;
				}			
			}
			correct = true;
		}
		return correct;				
     }     
            
	
	/**
	 * @return a representation of the solution on the board
	 */
     public String toString(){
	    //TODO
	    return "";
	}    

}
